﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace PPSkin
{
    [DefaultEvent("ValueChanged")]
    public class PPTrackBar : UserControl
    {
        [Description("值改变事件"), Category("自定义")]
        public event EventHandler ValueChanged;

        [Description("手动操作值改变事件"), Category("自定义")]
        public event EventHandler ManualValueChanged;

        private int dcimalDigits = 0;

        [Description("值小数精确位数"), Category("自定义")]
        public int DcimalDigits
        {
            get { return dcimalDigits; }
            set { dcimalDigits = value; }
        }

        private int lineWidth = 10;

        [Description("线宽度"), Category("自定义")]
        public int LineWidth
        {
            get { return lineWidth; }
            set { lineWidth = value; }
        }

        private long minValue = 0;

        [Description("最小值"), Category("自定义")]
        public long MinValue
        {
            get { return minValue; }
            set
            {
                if (minValue > m_value)
                    return;
                minValue = value;
                this.Refresh();
            }
        }

        private long maxValue = 100;

        [Description("最大值"), Category("自定义")]
        public long MaxValue
        {
            get { return maxValue; }
            set
            {
                if (value < m_value)
                    return;
                maxValue = value;
                this.Refresh();
            }
        }

        private long m_value = 0;

        [Description("值"), Category("自定义")]
        public long Value
        {
            get { return this.m_value; }
            set
            {
                if (value > maxValue || value < minValue)
                    return;
                //var v = (int)Math.Round((double)value, dcimalDigits);
                //if (m_value == value)
                //return;
                this.m_value = value;
                this.Invalidate();
                if (ValueChanged != null)
                {
                    ValueChanged(this, null);
                }
            }
        }

        private Color m_lineColor = Color.FromArgb(228, 231, 237);

        [Description("线颜色"), Category("自定义")]
        public Color LineColor
        {
            get { return m_lineColor; }
            set
            {
                m_lineColor = value;
                this.Refresh();
            }
        }

        private Color m_valueColor = Color.DodgerBlue;

        [Description("值颜色"), Category("自定义")]
        public Color ValueColor
        {
            get { return m_valueColor; }
            set
            {
                m_valueColor = value;
                this.Refresh();
            }
        }

        private Color ellipseColor = Color.White;

        [Description("圆按钮颜色"), Category("自定义")]
        public Color EllipseColor
        {
            get { return ellipseColor; }
            set
            {
                ellipseColor = value;
                this.Refresh();
            }
        }

        [Description("圆按钮边框颜色"), Category("自定义")]
        public Color EllipseBorderColor { get;set; }=Color.White;

        private bool isShowTips = true;

        [Description("点击滑动时是否显示数值提示"), Category("自定义")]
        public bool IsShowTips
        {
            get { return isShowTips; }
            set { isShowTips = value; }
        }

        [Description("显示数值提示的格式化形式"), Category("自定义")]
        public string TipsFormat { get; set; }

        [Description("数值是秒"), Category("自定义")]
        public bool ValueIsSecond { get; set; }

        private int radioButtonSize = 10;

        [Description("按钮大小"), Category("自定义")]
        public int RadioButtonSize
        {
            get { return radioButtonSize; }
            set
            {
                if (value < lineWidth)
                    return;
                radioButtonSize = value;
                this.Invalidate();
            }
        }

        [Description("显示按钮"), Category("自定义")]
        public bool ShowButton { get; set; } = true;

        private bool corners = true;

        [Description("是否启用圆角"), Category("自定义")]
        public bool Corners
        {
            get { return corners; }
            set
            {
                corners = value;
                this.Invalidate();
            }
        }

        private Color tipBackColor = Color.DodgerBlue;

        [Description("Tip气泡的背景色"), Category("自定义")]
        public Color TipBackColor
        {
            get { return tipBackColor; }
            set
            {
                tipBackColor = value;
            }
        }

        private Color tipForeColor = Color.White;

        [Description("Tip气泡的文本色"), Category("自定义")]
        public Color TipForeColor
        {
            get { return tipForeColor; }
            set
            {
                tipForeColor = value;
            }
        }

        private RectangleF m_lineRectangle;

        private RectangleF m_trackRectangle;

        public PPTrackBar()
        {
            this.Size = new Size(250, 30);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.Selectable, true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            this.UpdateStyles();
        }

        private bool blnDown = false;

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (m_lineRectangle.Contains(e.Location) || m_trackRectangle.Contains(e.Location))
            {
                blnDown = true;
                Value = minValue + ((e.Location.X - radioButtonSize / 2) * (maxValue - minValue)) / (this.Width - radioButtonSize);
                if (ManualValueChanged != null)
                {
                    ManualValueChanged(this, null);
                }
                ShowTips();
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (blnDown)
            {
                Value = minValue + ((e.Location.X - radioButtonSize / 2) * (maxValue - minValue)) / (this.Width - radioButtonSize);
                if (ManualValueChanged != null)
                {
                    ManualValueChanged(this, null);
                }
                ShowTips();
            }
            if (m_lineRectangle.Contains(e.Location))
            {
                this.Cursor = Cursors.Hand;
            }
            else
            {
                this.Cursor = Cursors.Default;
            }
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);

            blnDown = false;

            if (frmTips != null && !frmTips.IsDisposed)
            {
                frmTips.Close();
                frmTips = null;
            }
        }

        private FrmAnchorTips frmTips = null;

        private void ShowTips()
        {
            if (isShowTips)
            {
                string strValue = Value.ToString();
                if (!ValueIsSecond)//值不是秒
                {
                    if (!string.IsNullOrEmpty(TipsFormat))
                    {
                        try
                        {
                            strValue = Value.ToString(TipsFormat);
                        }
                        catch { }
                    }
                }
                else
                {
                    DateTime dt = new DateTime().AddSeconds(Value);
                    TimeSpan ts = dt - new DateTime();
                    strValue = ts.Hours.ToString().PadLeft(2, '0') + ":" + ts.Minutes.ToString().PadLeft(2, '0') + ":" + ts.Seconds.ToString().PadLeft(2, '0');
                }

                var p = this.PointToScreen(new Point((int)m_trackRectangle.X - 1, (int)m_trackRectangle.Y));

                if (frmTips == null || frmTips.IsDisposed || !frmTips.Visible)
                {
                    frmTips = FrmAnchorTips.ShowTips(new Rectangle(p.X, p.Y, (int)m_trackRectangle.Width, (int)m_trackRectangle.Height), strValue, this.Font.Name, (int)this.Font.Size, AnchorTipsLocation.TOP, tipBackColor, tipForeColor, autoCloseTime: -1);
                }
                else
                {
                    frmTips.RectControl = new Rectangle(p.X, p.Y, (int)m_trackRectangle.Width, (int)m_trackRectangle.Height);
                    frmTips.StrMsg = strValue;
                }
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics g = e.Graphics;
            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;

            Brush baseBrush = new SolidBrush(m_lineColor);
            Brush valueBrush = new SolidBrush(m_valueColor);
            Brush backBrush = new SolidBrush(this.BackColor);

            m_lineRectangle = new RectangleF(radioButtonSize / 2, (float)(this.Size.Height - lineWidth) / 2, this.Size.Width - radioButtonSize, lineWidth);
            GraphicsPath pathLine = PaintHelper.CreatePath(m_lineRectangle, corners ? lineWidth-2 : 0);// new GraphicsPath();
            GraphicsPath valueLine = PaintHelper.CreatePath(new RectangleF(radioButtonSize / 2, (float)(this.Size.Height - lineWidth) / 2, (int)((m_value - minValue) * m_lineRectangle.Width / (maxValue - minValue)), lineWidth), corners ? lineWidth-2 : 0);// new GraphicsPath();

            g.FillPath(baseBrush, pathLine);
            g.FillPath(valueBrush, valueLine);

            pathLine.AddRectangle(new Rectangle(-1, -1, this.Width + 1, this.Height + 1));
            g.FillPath(backBrush, pathLine);

            m_trackRectangle = new RectangleF(((float)(m_value - minValue) / (float)(maxValue - minValue)) * (this.Size.Width - radioButtonSize - 1), (float)(this.Size.Height - radioButtonSize) / 2, radioButtonSize, radioButtonSize);
            if (ShowButton)
            {
                g.FillEllipse(new SolidBrush(ellipseColor), m_trackRectangle);

                Pen pen = new Pen(EllipseBorderColor, 1f);
                g.DrawEllipse(pen, m_trackRectangle);
                pen.Dispose();
            }


            
            baseBrush.Dispose();
            valueBrush.Dispose();
            baseBrush.Dispose();
            pathLine.Dispose();
            valueLine.Dispose();
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            // PPTrackBar
            this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
            this.Name = "PPTrackBar";
            this.Size = new System.Drawing.Size(276, 29);
            this.ResumeLayout(false);
        }
    }
}